package com.steven.ourcontest.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.steven.ourcontest.R;
import com.steven.ourcontest.utils.DensityUtil;


public class RadiusView extends ConstraintLayout {

    private Path mPath = new Path();

    private int radiusLeftTop;
    private int radiusRightTop;
    private int radiusRightBottom;
    private int radiusLeftBottom;
    private int leftOffset;
    private int rightOffset;
    private int bottomOffset;
    private int topOffset;
    private int width;
    private int height;

    public RadiusView(Context context) {
        this(context, null);
    }

    public RadiusView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RadiusView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Paint mPaint = new Paint();
        mPaint.setColor(Color.WHITE);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        setWillNotDraw(false);

        TypedArray typeArray = context.obtainStyledAttributes(attrs,
                R.styleable.RadiusView);
        radiusLeftTop = (int) typeArray.getDimension(R.styleable.RadiusView_radiusLeftTop,
                0);
        radiusRightTop = (int) typeArray.getDimension(R.styleable.RadiusView_radiusRightTop,
                0);
        radiusRightBottom = (int) typeArray.getDimension(R.styleable.RadiusView_radiusRightBottom,
                0);
        radiusLeftBottom = (int) typeArray.getDimension(R.styleable.RadiusView_radiusLeftBottom,
                0);
        leftOffset = (int) typeArray.getDimension(R.styleable.RadiusView_leftOffset,
                0);
        rightOffset = (int) typeArray.getDimension(R.styleable.RadiusView_rightOffset,
                0);
        bottomOffset = (int) typeArray.getDimension(R.styleable.RadiusView_bottomOffset,
                0);
        topOffset = (int) typeArray.getDimension(R.styleable.RadiusView_topOffset,
                0);
        typeArray.recycle();


    }

    @Override
    public void draw(Canvas canvas) {
        width = getWidth();
        height = getHeight();
        if (width != 0 && height != 0) {
            SwapTwo tmp = new SwapTwo(radiusLeftTop, radiusLeftBottom);

            if (checkRadius(tmp, height)) {
                radiusLeftTop = tmp.getNumber1();
                radiusLeftBottom = tmp.getNumber2();
            }

            tmp.setNumber1(radiusRightTop);
            tmp.setNumber2(radiusRightBottom);
            if (checkRadius(tmp, height)) {
                radiusRightTop = tmp.getNumber1();
                radiusRightBottom = tmp.getNumber2();
            }

            tmp.setNumber1(radiusRightTop);
            tmp.setNumber2(radiusLeftTop);
            if (checkRadius(tmp, width)) {
                radiusRightTop = tmp.getNumber1();
                radiusLeftTop = tmp.getNumber2();
            }

            tmp.setNumber1(radiusLeftBottom);
            tmp.setNumber2(radiusRightBottom);
            if (checkRadius(tmp, width)) {
                radiusLeftBottom = tmp.getNumber1();
                radiusRightBottom = tmp.getNumber2();
            }

            mPath.moveTo(radiusLeftTop, 0);

            mPath.lineTo(width - radiusRightTop, 0);
            if (radiusRightTop != 0) {
                RectF rightTopRect = new RectF(width - 2 * radiusRightTop, 0, width, 2 * radiusRightTop);
                mPath.arcTo(rightTopRect, 270, 90, false);
            }

            mPath.lineTo(width, height - radiusRightBottom);
            if (radiusRightBottom != 0) {
                RectF rightBottomRect = new RectF(width - 2 * radiusRightBottom, height - 2 * radiusRightBottom, width, height);
                mPath.arcTo(rightBottomRect, 0, 90, false);
            }

            mPath.lineTo(radiusLeftBottom, height);
            if (radiusLeftBottom != 0) {
                RectF leftBottomRect = new RectF(0, height - 2 * radiusLeftBottom, 2 * radiusLeftBottom, height);
                mPath.arcTo(leftBottomRect, 90, 90, false);
            }

            mPath.lineTo(0, radiusLeftTop);
            if (radiusLeftTop != 0) {
                RectF leftTopRect = new RectF(0, 0, 2 * radiusLeftTop, 2 * radiusLeftTop);
                mPath.arcTo(leftTopRect, 180, 90, false);
            }
            mPath.close();
            canvas.save();
            //裁剪canvas，限定绘制区域
            canvas.clipPath(mPath);
            super.draw(canvas);
            canvas.restore();

            drawShadow();
        }

    }

    private void drawShadow() {
        if (getElevation()<=0)
            return;
        setClipToOutline(true);
        setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                Path path = new Path();
                path.moveTo(radiusLeftTop + rightOffset, bottomOffset);

                path.lineTo(width - radiusRightTop - leftOffset, bottomOffset);
                RectF rightTopRect = new RectF(width - 2 * radiusRightTop - leftOffset, bottomOffset, width - leftOffset, 2 * radiusRightTop + bottomOffset);
                path.arcTo(rightTopRect, 270, 90, false);

                path.lineTo(width - leftOffset, height - radiusRightBottom);
                RectF rightBottomRect = new RectF(width - 2 * radiusRightBottom - leftOffset, height - 2 * radiusRightBottom - topOffset, width - leftOffset, height - topOffset);
                path.arcTo(rightBottomRect, 0, 90, false);

                path.lineTo(radiusLeftBottom + rightOffset, height - topOffset);
                RectF leftBottomRect = new RectF(rightOffset, height - 2 * radiusLeftBottom - topOffset, 2 * radiusLeftBottom + rightOffset, height - topOffset);
                path.arcTo(leftBottomRect, 90, 90, false);

                path.lineTo(rightOffset, radiusLeftTop + bottomOffset);
                RectF leftTopRect = new RectF(rightOffset, bottomOffset, 2 * radiusLeftTop + rightOffset, 2 * radiusLeftTop + bottomOffset);
                path.arcTo(leftTopRect, 180, 90, false);
                //闭合路径
                path.close();
                outline.setConvexPath(path);
            }
        });
    }

    private boolean checkRadius(SwapTwo two, int max) {
        if (two.getNumber1() + two.getNumber2() >= max - DensityUtil.INSTANCE.dp2px(getContext(),2)) {
            int tmp1 = two.getNumber1();
            int tmp2 = two.getNumber2();
            two.setNumber1((tmp1 * max) / (tmp1 + tmp2) - DensityUtil.INSTANCE.dp2px(getContext(),2));
            two.setNumber2((tmp2 * max) / (tmp1 + tmp2) - DensityUtil.INSTANCE.dp2px(getContext(),2));
            return true;
        } else
            return false;
    }
}
